home *** CD-ROM | disk | FTP | other *** search
/ Aminet 43 / Aminet 43 (2001)(GTI - Schatztruhe)[!][Jun 2001].iso / Aminet / comm / tcp / Amster-source.lha / Amster_Install / Source / chat.c < prev    next >
C/C++ Source or Header  |  2001-03-11  |  13KB  |  491 lines

  1. /*
  2. ** Amster - Chat
  3. ** Copyright © 1999-2000 by Gürer Özen
  4. ** Copyright © 2000-2001 by Jacob Laursen
  5. **
  6. ** This program is free software; you can redistribute it and/or modify
  7. ** it under the terms of the GNU General Public License as published by
  8. ** the Free Software Foundation; either version 2 of the License, or
  9. ** (at your option) any later version.
  10. **
  11. ** This program is distributed in the hope that it will be useful,
  12. ** but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  14. ** GNU General Public License for more details.
  15. **
  16. ** You should have received a copy of the GNU General Public License
  17. ** along with this program; if not, write to the Free Software
  18. ** Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  19. */
  20.  
  21. #include "amster.h"
  22.  
  23. #include <MUI/NListview_mcc.h>
  24. #include <MUI/textinput_mcc.h>
  25.  
  26. #include "chatline.h"
  27. #include "amster_Cat.h"
  28.  
  29. channel chat_chans = NULL;
  30.  
  31. ULONG chat_new(struct IClass *cl, Object *obj, struct opSet *msg);
  32. Object *UserlistContextMenuBuild(struct IClass *cl, Object *obj, struct MUIP_NList_ContextMenuBuild *msg);
  33. MUI_LIST_DISP_DECL(chat_msgdisp, struct ChatMessage *m);
  34. MUI_LIST_DISP_DECL(userlistdisp, struct ChannelUserData *cud);
  35. MUI_LIST_DEST_DECL(userlistdest, struct ChannelUserData *cud);
  36. void channel_part(struct chatdata *data);
  37. void chat_say(struct chatdata *data, char *user, char *msg);
  38. void chat_sayf(struct chatdata *data, char *user, char *msg, ...);
  39. void chat_saysys(struct chatdata *data, char *msg);
  40. void chat_echo(struct chatdata *data, char *msg);
  41. void chat_command(struct chatdata *data);
  42.  
  43. struct MUI_CustomClass *UserlistContext;
  44.  
  45.  
  46. MUI_DISPATCH(chat_dispatch)
  47. {
  48.     struct chatdata *data;
  49.  
  50.     switch(msg->MethodID) {
  51.         case OM_NEW:
  52.             return(chat_new(cl, obj, (APTR)msg));
  53.         case OM_DISPOSE:
  54.             {
  55.             channel c = chat_chans;
  56.             data = INST_DATA(cl, obj);
  57.  
  58.             /* Update the linked list of channels */
  59.  
  60.             if (c == &data->chn) {
  61.                 chat_chans = c->next;
  62.                 /* The one to remove was the first in list,
  63.                    so we just point to the next one */
  64.             }
  65.             else while (c) {
  66.                 if (c->next == &data->chn)
  67.                     c->next = data->chn.next;
  68.                     /* The next one is the one to remove, so we point to the next
  69.                        one to that */
  70.                 c = c->next;
  71.             }
  72.  
  73.             break;
  74.             }
  75.         case CHAT_COMMAND:
  76.             data = INST_DATA(cl, obj);
  77.             chat_command(data);
  78.             return(0);
  79.         case CHAT_JOINCHANNEL:
  80.             data = INST_DATA(cl, obj);
  81.             if (gui_onlinestate < ONLINE) chat_saysys(data, (char *)MSG_CHAT_NOTCONNECTED);
  82.             else {
  83.                 data->chn.name = strdup((char *)(((muimsg)msg)->arg1));
  84.                 nap_sendbuf(NAPC_CHANNELJOIN, data->chn.name);
  85.                 data->chn.joinflag = 1;
  86.             }
  87.             return(0);
  88.         case CHAT_JOINACK:
  89.             data = INST_DATA(cl, obj);
  90.             data->chn.joinflag = 2;
  91.             DoMethod(data->rect, MUIM_Group_InitChange);
  92.             set(data->chantxt, MUIA_Text_Contents, data->chn.name);
  93.             DoMethod(data->rect, MUIM_Group_ExitChange);
  94.             chat_sayf(data, "\33b-->", (char *)MSG_CHAT_JOINED_YOU, data->chn.name);
  95.             return(0);
  96.         case CHAT_PUBLICMSGRECV:
  97.             data = INST_DATA(cl, obj);
  98.             if (stricmp(prf->user, (char *)(((muimsg)msg)->arg1)) != 0)
  99.                 chat_say(data, (char *)(((muimsg)msg)->arg1), (char *)(((muimsg)msg)->arg2));
  100.                 /* Only show messages from others */
  101.             return(0);
  102.         case CHAT_JOINMSG:
  103.             data = INST_DATA(cl, obj);
  104.             chat_sayf(data, "\33b-->", (char *)MSG_CHAT_JOINED_THIS, (char *)(((muimsg)msg)->arg1), (int)(((muimsg)msg)->arg2), nap_linktype[(int)(((muimsg)msg)->arg3)]);
  105.         case CHAT_USERLIST:
  106.             {
  107.             struct ChannelUserData *ud;
  108.             data = INST_DATA(cl, obj);
  109.             if (ud = malloc(sizeof(struct ChannelUserData))) {
  110.                 memset(ud, 0, sizeof(struct ChannelUserData));
  111.                 ud->Name = strdup((char *)(((muimsg)msg)->arg1));
  112.                 ud->Shares = (int)(((muimsg)msg)->arg2);
  113.                 ud->Link = (int)(((muimsg)msg)->arg3);
  114.                 DoMethod(data->userlist, MUIM_NList_InsertSingle, ud, MUIV_NList_Insert_Bottom);
  115.             }
  116.             return(0);
  117.             }
  118.         case CHAT_USERPART:
  119.             {
  120.             int i;
  121.             struct ChannelUserData *cud;
  122.             data = INST_DATA(cl, obj);
  123.  
  124.             chat_sayf(data,"\33b<--", (char *)MSG_CHAT_PART_THIS, (char *)(((muimsg)msg)->arg1));
  125.  
  126.             for (i=0; ; i++) {
  127.                 DoMethod(data->userlist, MUIM_NList_GetEntry, i, &cud);
  128.                 if (!cud) break;
  129.                 if (strcmp((char *)(((muimsg)msg)->arg1), cud->Name) == 0) {
  130.                     DoMethod(data->userlist, MUIM_NList_Remove, i);
  131.                     break;
  132.                 }
  133.             }
  134.  
  135.             return(0);
  136.             }
  137.         case CHAT_CHANNELPART:
  138.             data = INST_DATA(cl, obj);
  139.             if (data->chn.name) nap_sendbuf(NAPC_CHANNELPART, data->chn.name);
  140.             DoMethod(gui->iconpanel, PANEL_DISPOSECHAT, obj);
  141.             return(0);
  142.         case CHAT_CHANNELTOPIC:
  143.             data = INST_DATA(cl, obj);
  144.             set(data->topicstr, MUIA_String_Contents, ((muimsg)msg)->arg1);
  145.             return(0);
  146.  
  147.     }
  148.     return(DoSuperMethodA(cl, obj, msg));
  149. }
  150.  
  151.  
  152. ULONG chat_new(struct IClass *cl, Object *obj, struct opSet *msg)
  153. {
  154.     static struct Hook msgdispHook      = { {0,0}, &chat_msgdisp, NULL, NULL };
  155.     static struct Hook userlistdispHook = { {0,0}, &userlistdisp, NULL, NULL };
  156.     static struct Hook userlistdestHook = { {0,0}, &userlistdest, NULL, NULL };
  157.  
  158.     struct chatdata *data;
  159.     Object *rect, *chantxt, *topicstr, *msglist, *userlist, *msgstr;
  160.  
  161.     obj = (Object *)DoSuperNew(cl, obj,
  162.         MUIA_HelpNode, "chat",
  163.         MUIA_Window_Title, MSG_CHAT_TITLE,
  164.         MUIA_Window_ID, MAKE_ID('C','H','A','T'),
  165.         WindowContents, VGroup,
  166.             Child, rect = HGroup,
  167.                 Child, chantxt = TextObject,
  168.                     MUIA_HorizWeight, 0,
  169.                     MUIA_Text_Contents, MSG_CHAT_NONEJOINED,
  170.                 End,
  171.                 Child, topicstr = TextinputObject,
  172.                     StringFrame,
  173.                     MUIA_Textinput_Multiline, FALSE,
  174.                     MUIA_CycleChain, 1,
  175.                 End,
  176.             End,
  177.             Child, HGroup,
  178.                 Child, NListviewObject,
  179.                     MUIA_HorizWeight, 75,
  180.                     MUIA_NListview_NList, msglist = NListObject,
  181.                         ReadListFrame,
  182.                         MUIA_NList_Input, FALSE,
  183.                         MUIA_NList_Format, "BAR P=\33r,",
  184.                         MUIA_NList_DisplayHook, &msgdispHook,
  185.                         MUIA_NList_DefaultObjectOnClick, FALSE,
  186.                         MUIA_NList_AutoVisible, TRUE,
  187.                         MUIA_NList_AutoCopyToClip, TRUE,
  188.                         MUIA_NList_TypeSelect, MUIV_NList_TypeSelect_Char,
  189.                     End,
  190.                 End,
  191.                 Child, BalanceObject, End,
  192.                 Child, NListviewObject,
  193.                     MUIA_HorizWeight, 25,
  194.                     MUIA_NListview_NList, userlist = NewObject(UserlistContext->mcc_Class, NULL,
  195.                     /*userlist = NListObject,*/
  196.                         InputListFrame,
  197.                         MUIA_NList_DefaultObjectOnClick, FALSE,
  198.                         /* new */
  199.                         MUIA_NList_Format, "",
  200.                         MUIA_NList_DisplayHook, &userlistdispHook,
  201.                         MUIA_NList_DestructHook, &userlistdestHook,
  202.                         /* /new */
  203.                         /* old
  204.                         MUIA_NList_ConstructHook, MUIV_NList_ConstructHook_String,
  205.                         MUIA_NList_DestructHook, MUIV_NList_DestructHook_String,
  206.                          /old */
  207.                         MUIA_CycleChain, 1,
  208.                     TAG_DONE),
  209.                 End,
  210.             End,
  211.             Child, msgstr = TextinputObject,
  212.                 StringFrame,
  213.                 MUIA_CycleChain, 1,
  214.             End,
  215.         End,
  216.         TAG_MORE, msg->ops_AttrList);
  217.  
  218.     if (!obj) return(0);
  219.  
  220.     data = INST_DATA(cl,obj);
  221.     data->rect = rect;
  222.     data->chantxt = chantxt;
  223.     data->topicstr = topicstr;
  224.     data->msglist = msglist;
  225.     data->userlist = userlist;
  226.     data->msgstr = msgstr;
  227.  
  228.     data->chn.next = chat_chans;
  229.     chat_chans = &data->chn;
  230.     data->chn.joinflag = 0;
  231.     data->chn.name = NULL;
  232.     data->chn.win = obj;
  233.  
  234.     DoMethod(msgstr, MUIM_Notify, MUIA_String_Acknowledge, MUIV_EveryTime, obj, 1, CHAT_COMMAND);
  235.     DoMethod(msgstr, MUIM_Notify, MUIA_String_Acknowledge, MUIV_EveryTime, obj, 3, MUIM_Set, MUIA_Window_ActiveObject, msgstr);
  236.  
  237.     DoMethod(obj, MUIM_Notify, MUIA_Window_CloseRequest, TRUE, MUIV_Notify_Application, 5, MUIM_Application_PushMethod, obj, 1, CHAT_CHANNELPART);
  238. /*    DoMethod(obj, MUIM_Notify, MUIA_Window_CloseRequest, TRUE, MUIV_Notify_Application, 5, MUIM_Application_PushMethod, gui->iconpanel, 2, PANEL_DISPOSECHAT, obj);*/
  239.  
  240.     return((ULONG)obj);
  241. }
  242.  
  243.  
  244. MUI_DISPATCH(UserlistContextDispatcher)
  245. {
  246.     switch (msg->MethodID)
  247.     {
  248.         case MUIM_NList_ContextMenuBuild:
  249.             return (ULONG) UserlistContextMenuBuild(cl, obj, (struct MUIP_NList_ContextMenuBuild *)msg);
  250.             break;
  251.         case MUIM_ContextMenuChoice:
  252.             {
  253.             int item = muiUserData(((struct MUIP_ContextMenuChoice *)msg)->item);
  254.             switch (item) {
  255.                 case 0:
  256.                     DoMethod(gui->searchpanel, SEARCH_ADDTOHOTLIST);
  257.                     break;
  258.                 case 1:
  259.                     DoMethod(gui->searchpanel, SEARCH_NICKFROMLIST);
  260.                     break;
  261.             }
  262.             return NULL;
  263.             }
  264.     }
  265.     return(DoSuperMethodA(cl, obj, msg));
  266. }
  267.  
  268.  
  269. Object *UserlistContextMenuBuild(struct IClass *cl, Object *obj, struct MUIP_NList_ContextMenuBuild *msg)
  270. {
  271.     struct UserlistContextData *data = INST_DATA(cl, obj);
  272.  
  273.     if (msg->ontop || msg->pos == -1) {
  274.         return NULL; /* Default context menu when pointer isn't on an entry */
  275.     }
  276.     else {
  277.         gContextChoice = msg->pos;
  278.         return (
  279.             MenustripObject,
  280.                 Child, MenuObject,
  281.                     MUIA_Menu_Title, MSG_MAINCONTEXTMENU_TITLE,
  282.                     Child, data->MI_AddToHotlist = MenuitemObject,
  283.                         MUIA_Menuitem_Title, MSG_MAINCONTEXTMENU_ADD,
  284.                         MUIA_UserData, 0,
  285.                     End,
  286.                     Child, data->MI_BrowseUser = MenuitemObject,
  287.                         MUIA_Menuitem_Title, MSG_MAINCONTEXTMENU_BROWSE,
  288.                         MUIA_UserData, 1,
  289.                     End,
  290.                 End,
  291.             End);
  292.     }
  293. }
  294.  
  295.  
  296. MUI_LIST_DISP(chat_msgdisp, struct ChatMessage *m)
  297. {
  298.     *array++ = m->Nick;
  299.     *array = m->Msg;
  300.  
  301.     return(0);
  302. }
  303.  
  304.  
  305. MUI_LIST_DISP(userlistdisp, struct ChannelUserData *cud)
  306. {
  307.     static char line[64];
  308.  
  309.     sprintf(line, "%s (%ld)", cud->Name, cud->Shares);
  310.     cud->Display = strdup(line);
  311.     *array++ = cud->Display;
  312.     *array = "";
  313.  
  314.     return(0);
  315. }
  316.  
  317.  
  318. MUI_LIST_DEST(userlistdest, struct ChannelUserData *cud)
  319. {
  320.     free(cud->Name);
  321.     free(cud->Display);
  322.     free(cud);
  323.  
  324.     return(0);
  325. }
  326.  
  327. void chat_say(struct chatdata *data, char *user, char *msg)
  328. {
  329.     struct ChatMessage *m;
  330.  
  331.     m = malloc(sizeof(struct ChatMessage));
  332.     if (!m) return;
  333.  
  334.     m->Nick = strdup(user);
  335.     m->Msg = strdup(msg);
  336.  
  337.     DoMethod(data->msglist, MUIM_NList_InsertSingleWrap, m, MUIV_NList_Insert_Bottom, 2, NULL);
  338.     set(data->msglist, MUIA_NList_First, MUIV_NList_Active_Bottom);
  339. }
  340.  
  341.  
  342. void chat_sayf(struct chatdata *data, char *user, char *msg, ...)
  343. {
  344.     static char buf[1024];
  345.     va_list ap;
  346.  
  347.     va_start(ap, msg);
  348.     vsprintf(buf, msg, ap);
  349.     va_end(ap);
  350.     chat_say(data, user, buf);
  351. }
  352.  
  353.  
  354. void chat_saysys(struct chatdata *data, char *msg)
  355. {
  356.     chat_say(data,"\33b***",msg);
  357. }
  358.  
  359.  
  360. void chat_echo(struct chatdata *data, char *msg)
  361. {
  362.     chat_say(data,"\33b»",msg);
  363. }
  364.  
  365.  
  366. void chat_command(struct chatdata *data)
  367. {
  368.     u_long tmp;
  369.     char *com;
  370.  
  371.     GetAttr(MUIA_String_Contents, data->msgstr, &tmp);
  372.     com = (char *)tmp;
  373.  
  374.     DoMethod(data->msgstr, CHATLINE_ADD, com);
  375.  
  376.     if (com[0] == '/') {
  377.         if (strnicmp("join", com+1, 4) == 0 && strlen(com)>6) {
  378.             if (gui_onlinestate < ONLINE) chat_saysys(data, (char *)MSG_CHAT_NOTCONNECTED);
  379.             else {
  380.                 if (data->chn.name) channel_part(data);
  381.                 /* Leave channel in this window before joining a new one. */
  382.  
  383.                 data->chn.name = strdup(com+6);
  384.                 nap_sendbuf(NAPC_CHANNELJOIN, data->chn.name);
  385.                 data->chn.joinflag = 1;
  386.             }
  387.         }
  388.         else if (stricmp("leave", com+1) == 0) {
  389.             if (gui_onlinestate < ONLINE) chat_saysys(data, (char *)MSG_CHAT_NOTCONNECTED);
  390.             else channel_part(data);
  391.         }
  392.         else if (stricmp("list", com+1) == 0) {
  393.             DoMethod(gui->WI_ChannelList, MUIM_Set, MUIA_Window_Open, TRUE);
  394.             if (gui_onlinestate == ONLINE) DoMethod(gui->WI_ChannelList, CHANLIST_UPDATE);
  395.         }
  396.  
  397.     }
  398.     else {
  399.         if (gui_onlinestate < ONLINE) chat_saysys(data, (char *)MSG_CHAT_NOTCONNECTED);
  400.         else {
  401.             if (data->chn.joinflag>1) {
  402.                 chat_say(data, prf->user, com);
  403.                 sprintf(nap_buf,"%s %s", data->chn.name, com);
  404.                 nap_send(NAPC_PUBLICMSGSEND);
  405.             }
  406.             else {
  407.                 chat_saysys(data, (char *)MSG_CHAT_NOTJOINED);
  408.             }
  409.         }
  410.     }
  411.  
  412.     set(data->msgstr, MUIA_String_Contents, NULL);
  413. }
  414.  
  415.  
  416. void channel_part(struct chatdata *data)
  417. {
  418.     u_long item;
  419.  
  420.     nap_sendbuf(NAPC_CHANNELPART, data->chn.name);
  421.     chat_sayf(data,"\33b<--", (char *)MSG_CHAT_PART_YOU, data->chn.name);
  422.  
  423.     set(data->userlist, MUIA_NList_Quiet, MUIV_NList_Quiet_Visual);
  424.     while (1) {
  425.         DoMethod(data->userlist, MUIM_NList_GetEntry, 0, &item);
  426.         if (!item) break;
  427.         DoMethod(data->userlist, MUIM_NList_Remove, MUIV_NList_Remove_First);
  428.     }
  429.     set(data->userlist, MUIA_NList_Quiet, MUIV_NList_Quiet_None);
  430.     /* Clear users from list */
  431.  
  432.     data->chn.name = NULL;
  433.     /* Clear channel name */
  434.  
  435.     set(data->chantxt, MUIA_Text_Contents, MSG_CHAT_NONEJOINED);
  436.     /* Set channel name */
  437. }
  438.  
  439.  
  440. void chat_interpret(u_int com, char *data)
  441. {
  442.     channel c;
  443.  
  444.     switch (com) {
  445.         case NAPC_PUBLICMSGRECV:
  446.             c = chat_findchan(nap_token(&data));
  447.             if (!c) break;
  448.             DoMethod(c->win,CHAT_PUBLICMSGRECV,nap_token(&data),data);
  449.             break;
  450.         case NAPC_JOINACK:
  451.             c = chat_findchan(data);
  452.             if (!c) break;
  453.             DoMethod(c->win,CHAT_JOINACK);
  454.             break;
  455.         case NAPC_USERPART:
  456.             c = chat_findchan(nap_token(&data));
  457.             if (!c) break;
  458.             DoMethod(c->win,CHAT_USERPART,nap_token(&data));
  459.             break;
  460.         case NAPC_JOINMSG:
  461.             c = chat_findchan(nap_token(&data));
  462.             if (!c) break;
  463.             DoMethod(c->win, CHAT_JOINMSG, nap_token(&data), nap_itoken(&data), atoi(data));
  464.             break;
  465.         case NAPC_USERLIST:
  466.             c = chat_findchan(nap_token(&data));
  467.             if (!c) break;
  468.             DoMethod(c->win, CHAT_USERLIST, nap_token(&data), nap_itoken(&data), atoi(data));
  469.             break;
  470.         case NAPC_USERLISTEND:
  471.             break;
  472.         case NAPC_CHANNELTOPIC:
  473.             c = chat_findchan(nap_token(&data));
  474.             if (!c) break;
  475.             DoMethod(c->win, CHAT_CHANNELTOPIC, data);
  476.             break;
  477.     }
  478. }
  479.  
  480.  
  481. channel chat_findchan(char *name)
  482. {
  483.     channel c = chat_chans;
  484.  
  485.     while (c) {
  486.         if (stricmp(c->name, name) == 0) return(c);
  487.         c = c->next;
  488.     }
  489.     return(0);
  490. }
  491.